﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace System.IO
{
    public static class StreamExtensions
    {
        /// <summary>
        /// 将当前流数据写入另一个数据流中。
        /// </summary>
        /// <param name="source">源数据流</param>
        /// <param name="target">目标数据流</param>
        /// <param name="buffersize">指定一次写入的缓存大小</param>
        public static void WriteTo(this Stream source, Stream target, int buffersize = 10240)
        {
            if (!source.CanRead)
            {
                throw new Exception("the source stream must been readable.");
            }
            if (!target.CanWrite)
            {

                throw new Exception("the target stream must been writeable.");
            }
            var buf = new byte[buffersize];
            while (true)
            {
                var length = source.Read(buf, 0, buffersize);
                if (length == 0)
                {
                    break;
                }
                target.Write(buf, 0, length);
            }
        }
        /// <summary>
        /// 读取数据流中的所有字节
        /// </summary>
        /// <param name="source"></param>
        /// <param name="buffersize"></param>
        /// <returns></returns>
        public static byte[] ReadAsBytes(this Stream source, int buffersize = 10240)
        {
            if (!source.CanRead)
            {
                throw new Exception("the source stream must been readable.");
            }
            List<ArraySegment<byte>> list = new List<ArraySegment<byte>>();
            int total = 0;
            while (true)
            {
                var buf = new byte[buffersize];
                var length = source.Read(buf, 0, buffersize);
                if (length == 0)
                {
                    break;
                }
                total += length;
                list.Add(new ArraySegment<byte>(buf, 0, length));
            }
            byte[] all = new byte[total];
            int index = 0;
            foreach (var item in list)
            {
                for (int i = item.Offset; i < item.Count; i++)
                {
                    all[index++] = item.Array[i];
                }
            }
            return all;
        }

        /// <summary>
        /// 计算数据流的md5
        /// </summary>
        /// <param name="inputStream"></param>
        /// <returns></returns>
        public static string GetMD5ByHashAlgorithm(this Stream inputStream)
        {
            int bufferSize = 1024 * 16;//自定义缓冲区大小16K
            byte[] buffer = new byte[bufferSize];
            HashAlgorithm hashAlgorithm = new MD5CryptoServiceProvider();
            int readLength = 0;//每次读取长度
            var output = new byte[bufferSize];
            while ((readLength = inputStream.Read(buffer, 0, buffer.Length)) > 0)
            {
                //计算MD5
                hashAlgorithm.TransformBlock(buffer, 0, readLength, output, 0);
            }
            hashAlgorithm.TransformFinalBlock(buffer, 0, 0);
            string md5 = BitConverter.ToString(hashAlgorithm.Hash);
            hashAlgorithm.Clear();
            inputStream.Close();
            md5 = md5.Replace("-", "");
            return md5;
        }


    }
}
